package com.demo.modules.stock.util;

import cn.hutool.core.date.DateUtil;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

/**
 * 处理日期工具类
 */
public class DateUtils {

    /**
     * The UTC time zone (often referred to as GMT).
     */
    public static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("GMT");
    /**
     * 标准秒的毫秒数
     */
    public static final long MILLIS_PER_SECOND = 1000;
    /**
     * 标准分钟内的毫秒数
     */
    public static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
    /**
     * 标准小时内的毫秒数
     */
    public static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;

    /**
     * 将日期转换成字符串
     *
     * @param date
     * @param pattern 格式如:yyyy-MM-dd hh:mm:ss:SSS年月日时分秒毫秒
     * @return
     */
    public static String dateToString(Date date, String pattern) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        return simpleDateFormat.format(date);
    }

    public static Date setDate(int years, int months, int days, int hours, int minutes, int seconds, int milliSeconds) {
        Date date = new Date();
        Calendar c = Calendar.getInstance();
        c.setLenient(false);
        c.setTime(date);
        c.set(Calendar.YEAR, years);
        c.set(Calendar.MONTH, months);
        c.set(Calendar.DAY_OF_MONTH, days);
        c.set(Calendar.HOUR_OF_DAY, hours);
        c.set(Calendar.MINUTE, minutes);
        c.set(Calendar.SECOND, seconds);
        c.set(Calendar.MILLISECOND, milliSeconds);
        return c.getTime();
    }

    /**
     * 是否是同一天
     *
     * @param date1 the first date, not altered, not null
     * @param date2 the second date, not altered, not null
     * @return true if they represent the same day
     * @throws IllegalArgumentException if either date is <code>null</code>
     * @since 2.1
     */
    public static boolean isSameDay(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);
        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        if (cal1 == null || cal2 == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) && cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR)
                && cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
    }

    /**
     * 添加月份
     *
     * @param date
     * @param amount
     * @return
     */
    public static Date addMonths(Date date, int amount) {
        return add(date, Calendar.MONTH, amount);
    }

    /**
     * Adds a number of weeks to a date returning a new object. The original
     * date object is unchanged.
     *
     * @param date   the date, not null
     * @param amount the amount to add, may be negative
     * @return the new date object with the amount added
     * @throws IllegalArgumentException if the date is null
     */
    public static Date addWeeks(Date date, int amount) {
        return add(date, Calendar.WEEK_OF_YEAR, amount);
    }

    /**
     * Adds a number of days to a date returning a new object. The original date
     * object is unchanged.
     *
     * @param date   the date, not null
     * @param amount the amount to add, may be negative
     * @return the new date object with the amount added
     * @throws IllegalArgumentException if the date is null
     */
    public static Date addDays(Date date, int amount) {
        return add(date, Calendar.DAY_OF_MONTH, amount);
    }

    /**
     * Adds a number of hours to a date returning a new object. The original
     * date object is unchanged.
     *
     * @param date   the date, not null
     * @param amount the amount to add, may be negative
     * @return the new date object with the amount added
     * @throws IllegalArgumentException if the date is null
     */
    public static Date addHours(Date date, int amount) {
        return add(date, Calendar.HOUR_OF_DAY, amount);
    }

    // -----------------------------------------------------------------------

    /**
     * Adds a number of minutes to a date returning a new object. The original
     * date object is unchanged.
     *
     * @param date   the date, not null
     * @param amount the amount to add, may be negative
     * @return the new date object with the amount added
     * @throws IllegalArgumentException if the date is null
     */
    public static Date addMinutes(Date date, int amount) {
        return add(date, Calendar.MINUTE, amount);
    }

    // -----------------------------------------------------------------------

    /**
     * Adds a number of seconds to a date returning a new object. The original
     * date object is unchanged.
     *
     * @param date   the date, not null
     * @param amount the amount to add, may be negative
     * @return the new date object with the amount added
     * @throws IllegalArgumentException if the date is null
     */
    public static Date addSeconds(Date date, int amount) {
        return add(date, Calendar.SECOND, amount);
    }

    // -----------------------------------------------------------------------

    /**
     * Adds a number of milliseconds to a date returning a new object. The
     * original date object is unchanged.
     *
     * @param date   the date, not null
     * @param amount the amount to add, may be negative
     * @return the new date object with the amount added
     * @throws IllegalArgumentException if the date is null
     */
    public static Date addMilliseconds(Date date, int amount) {
        return add(date, Calendar.MILLISECOND, amount);
    }

    public static Date add(Date date, int calendarField, int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(calendarField, amount);
        return c.getTime();
    }

    // -----------------------------------------------------------------------

    /**
     * Sets the years field to a date returning a new object. The original date
     * object is unchanged.
     *
     * @param date   the date, not null
     * @param amount the amount to set
     * @return a new Date object set with the specified value
     * @throws IllegalArgumentException if the date is null
     * @since 2.4
     */
    public static Date setYears(Date date, int amount) {
        return set(date, Calendar.YEAR, amount);
    }

    // -----------------------------------------------------------------------

    /**
     * Sets the months field to a date returning a new object. The original date
     * object is unchanged.
     *
     * @param date   the date, not null
     * @param amount the amount to set
     * @return a new Date object set with the specified value
     * @throws IllegalArgumentException if the date is null
     * @since 2.4
     */
    public static Date setMonths(Date date, int amount) {
        return set(date, Calendar.MONTH, amount);
    }

    // -----------------------------------------------------------------------

    /**
     * Sets the day of month field to a date returning a new object. The
     * original date object is unchanged.
     *
     * @param date   the date, not null
     * @param amount the amount to set
     * @return a new Date object set with the specified value
     * @throws IllegalArgumentException if the date is null
     * @since 2.4
     */
    public static Date setDays(Date date, int amount) {
        return set(date, Calendar.DAY_OF_MONTH, amount);
    }

    // -----------------------------------------------------------------------

    /**
     * Sets the hours field to a date returning a new object. Hours range from
     * 0-23. The original date object is unchanged.
     *
     * @param date   the date, not null
     * @param amount the amount to set
     * @return a new Date object set with the specified value
     * @throws IllegalArgumentException if the date is null
     * @since 2.4
     */
    public static Date setHours(Date date, int amount) {
        return set(date, Calendar.HOUR_OF_DAY, amount);
    }

    // -----------------------------------------------------------------------

    /**
     * Sets the minute field to a date returning a new object. The original date
     * object is unchanged.
     *
     * @param date   the date, not null
     * @param amount the amount to set
     * @return a new Date object set with the specified value
     * @throws IllegalArgumentException if the date is null
     * @since 2.4
     */
    public static Date setMinutes(Date date, int amount) {
        return set(date, Calendar.MINUTE, amount);
    }

    // -----------------------------------------------------------------------

    /**
     * Sets the seconds field to a date returning a new object. The original
     * date object is unchanged.
     *
     * @param date   the date, not null
     * @param amount the amount to set
     * @return a new Date object set with the specified value
     * @throws IllegalArgumentException if the date is null
     * @since 2.4
     */
    public static Date setSeconds(Date date, int amount) {
        return set(date, Calendar.SECOND, amount);
    }

    // -----------------------------------------------------------------------

    /**
     * Sets the miliseconds field to a date returning a new object. The original
     * date object is unchanged.
     *
     * @param date   the date, not null
     * @param amount the amount to set
     * @return a new Date object set with the specified value
     * @throws IllegalArgumentException if the date is null
     * @since 2.4
     */
    public static Date setMilliseconds(Date date, int amount) {
        return set(date, Calendar.MILLISECOND, amount);
    }

    // -----------------------------------------------------------------------

    /**
     * Sets the specified field to a date returning a new object. This does not
     * use a lenient calendar. The original date object is unchanged.
     *
     * @param date          the date, not null
     * @param calendarField the calendar field to set the amount to
     * @param amount        the amount to set
     * @return a new Date object set with the specified value
     * @throws IllegalArgumentException if the date is null
     * @since 2.4
     */
    private static Date set(Date date, int calendarField, int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        // getInstance() returns a new object, so this method is thread safe.
        Calendar c = Calendar.getInstance();
        c.setLenient(false);
        c.setTime(date);
        c.set(calendarField, amount);
        return c.getTime();
    }

    /**
     * 获得前几天的日期
     *
     * @param date 原日期
     * @param days 天数
     * @return Date
     */
    public static Date getPreviousDay(Date date, int days) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int day = c.get(Calendar.DAY_OF_MONTH);
        c.set(Calendar.DAY_OF_MONTH, c.get(Calendar.DAY_OF_MONTH) - days);
        return c.getTime();
    }

    /**
     * 获取当前时间一周前日期
     *
     * @return
     */
    public static Date getLastWeekDate() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DATE, -7);
        return calendar.getTime();
    }

    /**
     * 获取当前时间前一个月的日期
     *
     * @return
     */
    public static Date getLastMonthDate() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.MONTH, -1);
        return calendar.getTime();
    }

    /**
     * 计算两个日期的时间差,返回时分秒毫秒
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return
     */
    public static String dateDif(Date start, Date end) {
        long dif = end.getTime() - start.getTime();
        if (dif < 0)
            return "-1";
        int sm = Integer.valueOf(dateToString(start, "yyyy-MM-dd hh:mm:ss:SSS").substring(20, 23));
        int em = Integer.valueOf(dateToString(end, "yyyy-MM-dd hh:mm:ss:SSS").substring(20, 23));
        long hours = dif / 1000 / 60 / 60;
        long minutes = dif / 1000 / 60 - hours * 60;
        long seconds = (dif - hours * 60 * 60 * 1000 - minutes * 60 * 1000) / 1000;
        long milliSeconds = (dif - hours * 60 * 60 * 1000 - minutes * 60 * 1000 - seconds * 1000);
        if (sm > em) {
            seconds++;
        }
        return hours + "小时" + minutes + "分钟" + seconds + "秒" + milliSeconds + "毫秒";
    }

    public static void main(String[] args) {
        String s = "2017-11-21";
        System.out.println(DateUtil.offsetDay(DateUtil.parseDate(s),20).toDateStr());


    }

}
